//
//  RootViewController.m
//  02 图片合成视频
//
//  Created by dllo on 16/3/12.
//  Copyright © 2016年 dllo. All rights reserved.
//
#import <MediaPlayer/MediaPlayer.h>
#import <QuartzCore/QuartzCore.h>
#import <CoreVideo/CoreVideo.h>
#import <CoreMedia/CoreMedia.h>
#import <AVFoundation/AVFoundation.h>

#import "RootViewController.h"

@interface RootViewController ()

// 保存图片路径
@property(nonatomic, strong)NSMutableArray *imageArr;

// 保存视频保存的路径
@property(nonatomic, copy)NSString *moviePath;

// 合成
- (IBAction)compose:(id)sender;

// 播放
- (IBAction)play:(id)sender;
@end

@implementation RootViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    
    self.imageArr = [NSMutableArray arrayWithObjects:[UIImage imageNamed:@"1.jpg"],[UIImage imageNamed:@"2.jpg"],[UIImage imageNamed:@"3.jpg"],[UIImage imageNamed:@"4.jpg"],[UIImage imageNamed:@"5.jpg"],[UIImage imageNamed:@"6.jpg"],[UIImage imageNamed:@"7.jpg"],[UIImage imageNamed:@"8.jpg"],[UIImage imageNamed:@"9.jpg"],[UIImage imageNamed:@"10.jpg"],[UIImage imageNamed:@"11.jpg"],[UIImage imageNamed:@"12.jpg"],[UIImage imageNamed:@"13.jpg"],[UIImage imageNamed:@"14.jpg"],[UIImage imageNamed:@"15.jpg"],[UIImage imageNamed:@"16.jpg"],[UIImage imageNamed:@"17.jpg"], nil];
    
}


// 合成
- (IBAction)compose:(id)sender {
    
    
    NSLog(@"开始合成");
    // 沙盒路径
    NSString *sanBoxPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];
    
    NSLog(@"%@",sanBoxPath);
    // 合成后的视频保存的路径
    self.moviePath = [NSString stringWithFormat:@"%@/movie.mov",sanBoxPath];
    
    // 视频的大小
    CGSize movieSize = CGSizeMake(320, 400);
    
    NSError *error = nil;
    
    unlink([self.moviePath UTF8String]);
    
    // 初始化压缩引擎
    AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:self.moviePath] fileType:AVFileTypeQuickTimeMovie error:&error];
    
    // 断言,就是希望程序在相应位置设定的条件不满足的时候抛出来，用NSParameterAssert让程序crash到相应位置，用来作安全检查
    NSParameterAssert(videoWriter);
    
    if(error){
        NSLog(@"error = %@",[error localizedDescription]);
    }
    // 对生成的视频的设置
    NSDictionary *videoSetting = [NSDictionary dictionaryWithObjectsAndKeys:AVVideoCodecH264,AVVideoCodecKey,[NSNumber numberWithInt:movieSize.width],AVVideoWidthKey,[NSNumber numberWithInt:movieSize.height],AVVideoHeightKey, nil];
    
    AVAssetWriterInput *writerInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSetting];
    NSDictionary *sourcePixelBufferAttributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:kCVPixelFormatType_32ABGR],kCVPixelBufferPixelFormatTypeKey, nil];
    
    AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput  sourcePixelBufferAttributes:sourcePixelBufferAttributesDictionary];
    NSParameterAssert(writerInput);
    NSParameterAssert([videoWriter canAddInput:writerInput]);
    
    if([videoWriter canAddInput:writerInput]){
        NSLog(@"1111");
    }
    else{
        NSLog(@"2222");
    }
    
    [videoWriter addInput:writerInput];
    
    [videoWriter startWriting];
    
    [videoWriter startSessionAtSourceTime:kCMTimeZero];
    
    
    // 将多张图片合成为一个视频文件
    dispatch_queue_t queue = dispatch_queue_create("mediaInputQueue", NULL);
    int __block frame = 0;

    [writerInput requestMediaDataWhenReadyOnQueue:queue usingBlock:^{
        
        while ([writerInput isReadyForMoreMediaData]) {
            if(++frame >= [self.imageArr count] * 10){
                [writerInput markAsFinished];
                [videoWriter finishWritingWithCompletionHandler:^{
                    
                    NSLog(@"结束了");
                    
                }];
                break;
            }
            
            CVPixelBufferRef buffer = NULL;
            // 和下面的CMTimeMake(frame, 5)一起控制视频的长度,和上面的 [self.imageArr count] * 10 中的10 是一个
            int idx = frame / 10;
            
            NSLog(@"idx == %d",idx);
            
            buffer = [self pixelBufferFromCGImage:[[self.imageArr objectAtIndex:idx] CGImage] size:movieSize];
            
            if(buffer){
                // 设置视频的时间
                if([adaptor appendPixelBuffer:buffer withPresentationTime:CMTimeMake(frame, 5)]){
                    NSLog(@"写入成功");
                }
                else{
                    NSLog(@"写入失败");
                    CFRelease(buffer);
                }
            }
        }
    }];
    
    
}

- (CVPixelBufferRef)pixelBufferFromCGImage:(CGImageRef)image size:(CGSize)size{
    
    NSDictionary *options =[NSDictionary dictionaryWithObjectsAndKeys:
                            [NSNumber numberWithBool:YES],kCVPixelBufferCGImageCompatibilityKey,
                            [NSNumber numberWithBool:YES],kCVPixelBufferCGBitmapContextCompatibilityKey,nil];
    CVPixelBufferRef pxbuffer =NULL;
    CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault,size.width,size.height,kCVPixelFormatType_32ARGB,(__bridge CFDictionaryRef _Nullable)(options),&pxbuffer);
    
    NSParameterAssert(status ==kCVReturnSuccess && pxbuffer !=NULL);
    
    CVPixelBufferLockBaseAddress(pxbuffer,0);
    void *pxdata =CVPixelBufferGetBaseAddress(pxbuffer);
    NSParameterAssert(pxdata !=NULL);
    
    CGColorSpaceRef rgbColorSpace=CGColorSpaceCreateDeviceRGB();
    CGContextRef context =CGBitmapContextCreate(pxdata,size.width,size.height,8,4*size.width,rgbColorSpace,kCGImageAlphaPremultipliedFirst);
    NSParameterAssert(context);
    
    
    // 设置视频中的图片的尺寸
    // 设置尺寸为图片的原始的尺寸
    // 注意:如果图片过小,或者过大都会在视频中显示的不合理
//    CGContextDrawImage(context,CGRectMake(0,0,CGImageGetWidth(image),CGImageGetHeight(image)), image);
    
    // 设置图片的尺寸和视频的尺寸一样大小
    CGContextDrawImage(context, CGRectMake(0, 0, size.width, size.height), image);
    
    CGColorSpaceRelease(rgbColorSpace);
    CGContextRelease(context);
    
    CVPixelBufferUnlockBaseAddress(pxbuffer,0);
    
    return pxbuffer;
}


// 播放
- (IBAction)play:(id)sender {
    
}






- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}




@end
